package com.ibeeking.found.common.db.aop;

import com.ibeeking.found.common.db.annotation.IgnoreDS;
import com.ibeeking.found.common.db.util.DataSourceUtils;
import com.ibeeking.found.common.response.ResponseCodeEnum;
import com.ibeeking.found.job.annotation.EnableJob;
import com.ibeeking.gmc.job.core.handler.annotation.XxlJob;
import com.ibeeking.found.job.model.BusinessKeyModel;
import com.ibeeking.nematos.constants.enums.LogConstant;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import org.apache.logging.log4j.ThreadContext;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;

import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @ClassName DataSourceAop
 * @Description
 * @Author ibeeking
 * @Date 2020-11-05 11:32
 **/
@Aspect
@ConditionalOnClass(EnableJob.class)
@Component
@Order(-1)
public class JobHandlerDataSourceAop {

    private static final String NON_CHANGE_DB = "-1";

    @Pointcut("execution(* com.ibeeking..*.*JobHandler.*(..))")
    public void changeDSHandle() {
    }

    @Around(("changeDSHandle()"))
    public Object changeDSHandle(ProceedingJoinPoint point) throws Throwable {
        MethodSignature signature = (MethodSignature) point.getSignature();
        IgnoreDS ignoreDS = signature.getMethod().getAnnotation(IgnoreDS.class);
        if (null != ignoreDS) {
            return point.proceed();
        }
        XxlJob xxlJob = signature.getMethod().getAnnotation(XxlJob.class);
        if (null == xxlJob) {
            return point.proceed();
        }
        String tenantId = point.getArgs()[0].toString();
        if (StringUtils.isEmpty(tenantId)) {
            throw new BusinessException(ResponseCodeEnum.TENANT_ID_NOT_EXIST.getCode(), ResponseCodeEnum.TENANT_ID_NOT_EXIST.getMsg());
        } else {
            BusinessKeyModel businessKeyModel = JsonUtils.fromJson(tenantId, BusinessKeyModel.class);
            if (StringUtils.isEmpty(businessKeyModel.getBusinessKey())) {
                throw new BusinessException(ResponseCodeEnum.TENANT_ID_NOT_EXIST.getCode(), ResponseCodeEnum.TENANT_ID_NOT_EXIST.getMsg());
            }
            tenantId = businessKeyModel.getBusinessKey();
            ThreadContext.put(LogConstant.TENANT_ID, tenantId);
        }
        try {
            //切换数据源
            DataSourceUtils.loadDataSource(tenantId, DataSourceUtils.writeOrRead(point, signature));
            return point.proceed();
        } finally {
            //清除数据源
            DataSourceUtils.clear();
            ThreadContext.remove(LogConstant.TENANT_ID);
        }

    }
}
